import constants from '@/constants';
import { AnalysisTrendDto, AnalysisUserDto } from '@/dtos/analysis.dto';
import { OrderStatusEnum, TokenStatusEnum } from '@/enums';
import { ok } from '@/utils';
import { Body, Controller, Post } from '@nestjs/common';
import dayjs from 'dayjs';
import { BaseController } from './base.controller';

@Controller('analysis')
export class AnalysisController extends BaseController {
  @Post('admin/user')
  async user(@Body() dto: AnalysisUserDto) {
    const currentDate = dayjs();
    const res = await this.prisma.$queryRawUnsafe(`
        SELECT
            (
                SELECT COUNT(u.id) 
                FROM User AS u
            ) AS total,
            (
                SELECT COUNT(u.id) 
                FROM User AS u
                WHERE 
                      CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') >= '${currentDate.startOf('day').format('YYYY-MM-DD HH:mm:ss')}'
                    AND 
                      CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') <= '${currentDate.endOf('day').format('YYYY-MM-DD HH:mm:ss')}'
            ) AS today,
            (
                SELECT COUNT(u.id) 
                FROM User AS u
                WHERE 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') >= '${currentDate.subtract(1, 'days').startOf('day').format('YYYY-MM-DD HH:mm:ss')}'
                    AND 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') <= '${currentDate.subtract(1, 'days').endOf('day').format('YYYY-MM-DD HH:mm:ss')}'
            ) AS yesterday,
            (
                SELECT COUNT(u.id) 
                FROM User AS u
                WHERE 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') >= '${currentDate.startOf('week').format('YYYY-MM-DD HH:mm:ss')}'
                    AND 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') <= '${currentDate.endOf('week').format('YYYY-MM-DD HH:mm:ss')}'
            ) AS thisWeek,
            (
                SELECT COUNT(u.id) 
                FROM User AS u
                WHERE 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') >= '${currentDate.startOf('month').format('YYYY-MM-DD HH:mm:ss')}'
                    AND 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') <= '${currentDate.endOf('month').format('YYYY-MM-DD HH:mm:ss')}'
            ) AS thisMonth,
            (
                SELECT COUNT(u.id) 
                FROM User AS u
                WHERE 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') >= '${currentDate.subtract(3, 'days').startOf('day').format('YYYY-MM-DD HH:mm:ss')}'
                    AND 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') <= '${currentDate.endOf('day').format('YYYY-MM-DD HH:mm:ss')}'
            ) AS lastThreeDays,
            (
                SELECT COUNT(u.id) 
                FROM User AS u
                WHERE 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') >= '${currentDate.subtract(7, 'days').startOf('day').format('YYYY-MM-DD HH:mm:ss')}'
                    AND 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') <= '${currentDate.endOf('day').format('YYYY-MM-DD HH:mm:ss')}'
            ) AS lastSevenDays,
            (
                SELECT COUNT(u.id) 
                FROM User AS u
                WHERE 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') >= '${currentDate.subtract(1, 'weeks').startOf('week').format('YYYY-MM-DD HH:mm:ss')}'
                    AND 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') <= '${currentDate.subtract(1, 'weeks').endOf('week').format('YYYY-MM-DD HH:mm:ss')}'
            ) AS lastWeek, 
            (
                SELECT COUNT(u.id) 
                FROM User AS u
                WHERE 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') >= '${currentDate.subtract(1, 'months').startOf('month').format('YYYY-MM-DD HH:mm:ss')}'
                    AND 
                        CONVERT_TZ(u.createdAt, 'UTC', 'Asia/Shanghai') <= '${currentDate.subtract(1, 'months').endOf('month').format('YYYY-MM-DD HH:mm:ss')}'
            ) AS lastMonth,
            (
                SELECT COUNT(u.id)
                FROM User AS u
                WHERE u.idCard IS NOT NULL
            ) AS realname,
            (
                SELECT COUNT(DISTINCT o.ownerId)
                FROM \`Order\` AS o
                WHERE o.status = ${OrderStatusEnum.COMPLETED}
            ) AS paid,
            (
                SELECT COUNT(DISTINCT t.ownerId)
                FROM \`Token\` AS t
                WHERE t.ownerId != ${constants.default.ownerId}
                    AND t.status != ${TokenStatusEnum.DESTROYED}
            ) AS hold
     `);
    return ok({
      ...(!!res ? res[0] : {}),
      active: await this.redis.scard(
        `visit:${currentDate.format('YYYY-MM-DD')}`,
      ),
    });
  }

  @Post('admin/trend')
  async trend(@Body() { startDate, endDate }: AnalysisTrendDto) {
    const res = await this.prisma.$queryRawUnsafe<any>(`
        SELECT
            DATE_FORMAT(t.date, '%Y-%m-%d') AS date,
            SUM(t.total) AS amount,
            COUNT(t.id) AS volume
        FROM \`Order\` AS t
        WHERE t.status = ${OrderStatusEnum.COMPLETED}
            ${
              startDate
                ? `AND t.date >= '${dayjs(startDate).format(
                    'YYYY-MM-DD HH:mm:ss',
                  )}'`
                : ''
            }
            ${
              endDate
                ? `AND t.date <= '${dayjs(endDate).format(
                    'YYYY-MM-DD HH:mm:ss',
                  )}'`
                : ''
            }
        GROUP BY date
        ORDER BY date ASC
     `);
    return ok(
      res?.map((item) => ({
        ...item,
        amount: Number(item.amount),
      })) || [],
    );
  }
}
